package com.sfac.modules.account.service.serviceimpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sfac.modules.account.domain.Role;
import com.sfac.modules.account.domain.User;
import com.sfac.modules.account.domain.UserRole;
import com.sfac.modules.account.mapper.UserMapper;
import com.sfac.modules.account.mapper.UserRoleMapper;
import com.sfac.modules.account.service.UserService;
import com.sfac.modules.common.vo.Result;
import com.sfac.modules.common.vo.Search;
import com.sfac.modules.common.vo.StatusCode;
import com.sfac.utils.MD5Util;
import com.sfac.utils.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author:唐琳的爹
 * @BelongsProject:hqyj_springboot
 * @BelongsPackage:com.sfac.modules.account.service.serviceimpl
 * @CreateTime:2022/8/27 14:20:39
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RedisUtils redisUtils;


    /**
     * 用户登录方法
     * @param user
     * @return
     */
    @Override
    public Result<String> login(User user) {

        /*LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        // 根据用户名查询用户信息
        queryWrapper.eq(User::getUserName,user.getUserName());
        User u = userMapper.selectOne(queryWrapper);
        // 查看用户的状态
        if (u == null){
            return new Result<>(StatusCode.ERR,"用户不存在!");
        }
        if (u.getStatus() == 0){
            return new Result<>(StatusCode.ERR,"账号已经被封禁!");
        }
        if (!u.getPassWord().equals(MD5Util.getMD5(user.getPassWord()))){
            return new Result<>(StatusCode.ERR,"密码错误!");
        }
        return new Result<>(StatusCode.SUCCESS,"登录成功!");*/

        // shiro登录

        // 获取登录次数,看是否为3次
        String errorLoginKey = String.format("errorLoginCount%s",user.getUserName());
        int count = redisUtils.get(errorLoginKey) == null ? 0 :
                (Integer)redisUtils.get(errorLoginKey);
        if (count > 3){
            return new Result<>(StatusCode.ERR,"登录失败,账号已被锁定");
        }

        // 得到 subject
        Subject subject = SecurityUtils.getSubject();
        // 封装一个令牌
        UsernamePasswordToken token = new UsernamePasswordToken(
                user.getUserName(),
                MD5Util.getMD5(user.getPassWord()));
        // 调用登录方法
        try {

        subject.login(token);
        // 资源授权

        // 获取当前用户存入session
        User u = (User)subject.getPrincipal();
        subject.getSession().setAttribute("user",u);

        // 将登录次数置零
        redisUtils.set(errorLoginKey,0);

        }catch (UnknownAccountException e){
            // 账号错误
        }catch (IncorrectCredentialsException e){
            // 密码错误
        }catch (Exception e){
            // 将登录错误次数自加1
            redisUtils.increment(errorLoginKey,1);

            // 判断登录的总次数是否大于3次，是则设置该key过期时间
            count = redisUtils.get(errorLoginKey) == null ? 0 :
                    (Integer)redisUtils.get(errorLoginKey);

            String errorMsg = "";

            if (count < 3){
                errorMsg = String.format("您已经连续错误登录了%d次,还有%d次机会",count,(3-count));

            }else {
                errorMsg = "您已经错误登录3次,账号已经被锁定";
                redisUtils.expire(errorLoginKey,15);
            }
            e.printStackTrace();
            return new Result<>(StatusCode.ERR,errorMsg);
        }
        return new Result<>(StatusCode.SUCCESS,"登录成功");
    }


    /**
     * 注册方法
     * @param user
     * @return
     */
    @Override
    @Transactional
    public Result<String> register(User user){

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        // 根据用户名查询用户信息
        queryWrapper.eq(User::getUserName,user.getUserName());
        User u = userMapper.selectOne(queryWrapper);
        // 核验用户名
        if (u != null){
            return new Result<>(StatusCode.ERR,"用户已存在!");
        }
            user.setCreateTime(LocalDateTime.now());
            user.setUpdateTime(LocalDateTime.now());
            user.setPassWord(MD5Util.getMD5(user.getPassWord()));
            int num = userMapper.insert(user);



        for (Role r:user.getRoles()){
                userRoleMapper.insert(new UserRole(user.getId(),r.getId()));
            }
        return new Result<>(StatusCode.SUCCESS,"注册成功");
    }

    /**
     * 分页查询
     * @param search
     * @return
     */
    @Override
    public Result<Page> getUserBySearchBean(Search search) {
        // 初始化方法
        search.init();
        // 创建分页条件
        Page<User> page = new Page<>(search.getCurrentPage(), search.getPageSize());
        // 创建查询条件
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.like(StringUtils.isNotBlank(search.getKeyWord()),User::getUserName,search.getKeyWord())
           .orderBy(true,"asc".equalsIgnoreCase(search.getDirection()),User::getUserName);
        // 查询
        Page<User> userPage = userMapper.selectPage(page, lqw);
        return new Result<Page>(StatusCode.SUCCESS,"查询成功",userPage);
    }

    /**
     * 查询用户
     * @param id
     * @return
     */
    @Override
    public Result<User> getUserById(String id) {
        User user = userMapper.selectById(id);
        user.setRoles(userRoleMapper.selectRoleByUserId(user.getId()));
        return new Result<>(StatusCode.SUCCESS,"查询成功",user);
    }

    /**
     * 删除用户
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Result<User> deleteUserById(String id) {
        userMapper.deleteById(id);
        LambdaQueryWrapper<UserRole> lqw = new LambdaQueryWrapper<>();
        lqw.eq(UserRole::getUserId,id);
        userRoleMapper.delete(lqw);
        return new Result<>(StatusCode.SUCCESS,"删除成功");
    }

    /**
     * 修改用户
     * @param user
     * @return
     */
    @Override
    public Result<User> updateUser(User user) {
        userMapper.updateById(user);
        LambdaQueryWrapper<UserRole> lqw = new LambdaQueryWrapper<>();
        lqw.eq(UserRole::getUserId,user.getId());

        if (user.getRoles() != null) {

                userRoleMapper.delete(lqw);

            user.getRoles().stream()
                    .forEach(item -> {
                        userRoleMapper.insert(
                                new UserRole(user.getId(), item.getId())
                        );
                    });
        }

        return new Result<>(StatusCode.SUCCESS,"修改成功");
    }

    /**
     * 根据用户名查询用户信息
     * @param userName
     * @return
     */
    @Override
    public User getUserByUserName(String userName) {
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getUserName,userName);
        User user = userMapper.selectOne(lqw);
        return user;
    }

}
